package com.aos.iot.socket.common.config;

import cn.hutool.extra.spring.SpringUtil;
import com.aos.iot.socket.common.ack.AckManager;
import com.aos.iot.socket.common.channel.CommonChannelInitializer;
import com.aos.iot.socket.common.client.ClientBoxFactor;
import com.aos.iot.socket.common.client.IClientBox;
import com.aos.iot.socket.common.handler.AbstractHandler;
import com.aos.iot.socket.common.handler.AbstractHandlerFactor;
import com.aos.iot.socket.common.message.Message;
import com.aos.iot.socket.common.parser.DataParser;
import com.aos.iot.socket.common.parser.DataParserFactor;
import com.aos.iot.socket.common.parser.Parser;
import com.aos.iot.socket.common.parser.ParserFactor;
import com.aos.iot.socket.common.scheduler.CancelableScheduler;
import com.aos.iot.socket.common.scheduler.HashedWheelTimeoutScheduler;
import com.aos.iot.socket.common.annotation.CmdEventAnnotationScanner;
import com.aos.iot.socket.common.protocol.IProtocol;
import com.aos.iot.socket.common.protocol.ProtocolFactor;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;

import java.util.List;

public class CommonConfiguration {

    @Bean
    @ConditionalOnMissingBean(SpringUtil.class)
    public SpringUtil springUtil() {
        return new SpringUtil();
    }

    @Bean
    @ConditionalOnMissingBean(ProtocolFactor.class)
    public ProtocolFactor protocolFactor(List<IProtocol> protocols) {
        return new ProtocolFactor(protocols);
    }

    @Bean
    @ConditionalOnMissingBean(AbstractHandlerFactor.class)
    public AbstractHandlerFactor abstractHandlerFactor(List<AbstractHandler> handlers) {
        return new AbstractHandlerFactor(handlers);
    }

    @Bean
    @ConditionalOnMissingBean(ChannelInitializer.class)
    public ChannelInitializer<? extends Channel> channelInitializer(ProtocolFactor protocolFactor, AbstractHandlerFactor abstractHandlerFactor) {
        return new CommonChannelInitializer(protocolFactor, abstractHandlerFactor);
    }

    @Bean
    @ConditionalOnMissingBean(CancelableScheduler.class)
    public CancelableScheduler cancelableScheduler() {
        return new HashedWheelTimeoutScheduler();
    }

    @Bean
    @ConditionalOnMissingBean(AckManager.class)
    public AckManager ackManager(CancelableScheduler scheduler) {
        return new AckManager(scheduler);
    }

    @Bean
    @ConditionalOnMissingBean(CmdEventAnnotationScanner.class)
    public CmdEventAnnotationScanner cmdEventAnnotationScanner() {
        return new CmdEventAnnotationScanner();
    }

    @Bean
    @ConditionalOnMissingBean(ParserFactor.class)
    public ParserFactor parserFactor(List<Parser<? extends Message>> parsers) {
        return new ParserFactor(parsers);
    }

    @Bean
    @ConditionalOnMissingBean(DataParserFactor.class)
    public DataParserFactor dataParserFactor(List<DataParser> dataParsers) {
        return new DataParserFactor(dataParsers);
    }

    @Bean
    @ConditionalOnMissingBean(ClientBoxFactor.class)
    public ClientBoxFactor clientBoxFactor(List<IClientBox> clientBoxes) {
        return new ClientBoxFactor(clientBoxes);
    }
}
